home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Developer Toolbox 6.1
/
SGI Developer Toolbox 6.1 - Disc 4.iso
/
public
/
SciAn
/
src
/
ScianLVR5000.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-01
|
11KB
|
523 lines
/*ScianLVR5000.c
Eric Pepke
Controls the LVR5000 video recorder
This file controls the Sony LVR-5000 videodisc recorder. It may be able
to control other models in the Sony line as well, but this is the only one
that we have. It currently runs only on the Silicon Graphics IRIS
workstation, but should be easy to make run on other systems.
To make this recorder work, you need to get a video signal from the
workstation to the recorder, and connect the recorder to the workstation
via a serial port.
The video signal can either be the standard IRIS RGB signal run through
a scan converter, or the direct IRIS RGB output when the IRIS is set to
"NTSC" mode. Don't hook the high-resolution output directly to the
recorder ever! The recorder tries to sync with the incoming signal, and
that can't be good for the servos.
The serial signal can go to any port on the back of the IRIS. The default
port which is used is gotten from the environment variable SCIAN_RECORDER_DEV.
If that environment variable is not present, then the #define'd value
of LVR5000_DEV from ScianLVR5000.h is used. The port is set to 9600 baud
by default. This can all be changed via the control panel of the recorder.
Oh, yes. In order for the machine to work, the LVR-5000 has to be set to
"Remote" operation via the front panel.
Thanks to Roland Schweitzer for the idea of using an environment variable
as an interim solution.
*/
#include "Scian.h"
#include "ScianTypes.h"
#include "ScianWindows.h"
#include "ScianDialogs.h"
#include "ScianIDs.h"
#include "ScianLVR5000.h"
#include "ScianErrors.h"
#include "ScianColors.h"
#include "ScianRecorders.h"
#ifdef TERMIO
/*Timeout in seconds*/
#define LVRTIMEOUT 5
/*Retries*/
#define NRETRIES 3
int debug = 0;
static ObjPtr ConnectLVR5000();
/*Internal prototypes*/
#ifdef PROTO
static void SendPort(int, char);
static int OpenPort(char *, int);
static int SendCmd(int, int);
static int WaitForResponse(int);
static int WaitALongTimeForResponse(int);
static int Read5Digits(int);
static Bool WaitForCompletion(int);
static int SendNumber(int, int);
#endif
#ifdef PROTO
static void SendPort(int portDev, char c)
#else
static void SendPort(portDev, c)
int portDev;
char c;
#endif
{
write(portDev, &c, 1);
}
#ifdef PROTO
static int OpenPort(char *devName, int baudRate)
#else
static int OpenPort(devName, baudRate)
char *devName;
int baudRate;
#endif
/*Opens a port to the recorder, returns it if successful*/
{
int portDev;
struct termio ioStuff;
ObjPtr var;
portDev = open(devName, O_RDWR | O_NDELAY | O_EXCL);
if (portDev < 0)
{
return portDev;
}
ioctl(portDev, TCGETA, &ioStuff);
ioStuff . c_oflag = 0;
ioStuff . c_iflag = IGNBRK;
ioStuff . c_lflag = 0;
/*Make cflag from baud rate*/
switch(baudRate)
{
case RB_300:
ioStuff . c_cflag = (unsigned short) (B300 | CS8 | CLOCAL | CREAD | CSTOPB);
break;
case RB_1200:
ioStuff . c_cflag = (unsigned short) (B1200 | CS8 | CLOCAL | CREAD);
break;
case RB_2400:
ioStuff . c_cflag = (unsigned short) (B2400 | CS8 | CLOCAL | CREAD);
break;
case RB_4800:
ioStuff . c_cflag = (unsigned short) (B4800 | CS8 | CLOCAL | CREAD);
break;
case RB_9600:
ioStuff . c_cflag = (unsigned short) (B9600 | CS8 | CLOCAL | CREAD);
break;
case RB_19200:
ioStuff . c_cflag = (unsigned short) (B19200 | CS8 | CLOCAL | CREAD);
break;
}
ioStuff . c_cc[4] = 1;
ioStuff . c_cc[0] = 1;
ioctl(portDev, TCSETA, &ioStuff);
return portDev;
}
static int SendCmd(portDev, number)
int portDev;
int number;
/*Sends out command name with number. Returns true iff successful*/
{
int response;
SendPort(portDev, number);
response = WaitForResponse(portDev);
switch (response)
{
case ACK:
return true;
case NAK:
return false;
case -1:
return false;
default:
return false;
}
}
static int WaitForResponse(portDev)
int portDev;
/*Waits for a response from the sony and returns it or -1 if it timed out
or is closed*/
{
char retVal;
long startTime, curTime;
struct tms buffer;
startTime = times(&buffer);
do
{
if (read(portDev, &retVal, 1))
{
return retVal;
}
curTime = times(&buffer);
} while (curTime < startTime + LVRTIMEOUT * HEARTBEAT);
return -1;
}
static int WaitALongTimeForResponse(portDev)
int portDev;
/*Waits a long time for a response from the sony and returns it or -1 if it
timed out or is closed*/
{
char retVal;
long startTime, curTime;
struct tms buffer;
startTime = times(&buffer);
do
{
if (read(portDev, &retVal, 1))
{
return retVal;
}
curTime = times(&buffer);
} while (curTime < startTime + 400 * HEARTBEAT);
return -1;
}
#if 0
int GetStatus(status)
char status[5];
/*Gets a status from the recorder and returns it in status. Returns true iff
successful*/
{
long startTime, curTime;
struct tms buffer;
int k;
char stat;
SendPort(STATUS_INQ);
for (k = 0; k < 5; ++k)
{
startTime = times(&buffer);
do
{
if (read(portDev, &stat, 1))
{
status[k] = stat;
goto oneMore;
}
curTime = times(&buffer);
} while (curTime < startTime + LVRTIMEOUT * HEARTBEAT);
return 0;
oneMore:;
}
return 1;
}
#endif
static ObjPtr ConnectLVR5000(object)
ObjPtr object;
/*Connects to the LVR5000. Returns true iff successful*/
{
int portDev;
int k;
ObjPtr var;
char *devName;
int baudRate;
MakeVar(object, PORTDEV);
var = GetStringVar("ConnectLVR5000", object, PORTDEV);
if (var)
{
devName = GetString(var);
}
else
{
devName = LVR5000_DEV;
}
MakeVar(object, BAUDRATE);
var = GetIntVar("ConnectTQ2026F", object, BAUDRATE);
if (var)
{
baudRate = GetInt(var);
}
else
{
baudRate = RB_9600;
}
/*Open a port*/
portDev = OpenPort(devName, baudRate);
if (portDev < 0)
{
return ObjFalse;
}
/*Now that a port is open, connect to it*/
for (k = 0; k < NRETRIES; ++k)
{
if (SendCmd(portDev, CONNECT_TO_PROCESSOR))
{
SendCmd(portDev, COLOR_MODE);
SendCmd(portDev, NTSC_MODE);
SendCmd(portDev, ALL_CLEAR);
SendCmd(portDev, FRAME_NO_MODE);
SetVar(object, PORTNUMBER, NewInt(portDev));
return ObjTrue;
}
}
close(portDev);
return ObjFalse;
}
static int Read5Digits(portDev)
int portDev;
/*Reads a five digit integer from portDev. Returns -1 on timeout*/
{
int k;
int cum;
cum = 0;
for (k = 0; k < 5; ++k)
{
int digit;
digit = WaitForResponse(portDev);
if (digit >= '0' && digit <= '9')
{
cum = cum * 10 + digit - '0';
}
else
{
return -1;
}
}
return cum;
}
static int SendNumber(portDev, num)
int portDev;
int num;
/*Sends a number followed by ENTER to the recorder*/
{
char numStr[10];
int k;
sprintf(numStr, "%d", num);
for (k = 0; numStr[k]; ++k)
{
if (!SendCmd(portDev, numStr[k])) return false;
}
return SendCmd(portDev, ENTER);
}
static Bool WaitForCompletion(portDev)
int portDev;
{
if (WaitALongTimeForResponse(portDev) == COMPLETION)
{
return true;
}
else
{
return false;
}
}
static ObjPtr PrepareToRecordLVR5000(object, nFrames)
ObjPtr object;
long nFrames;
/*Prepares to record nFrames on an LVR5000. Returns true iff successful.*/
{
ObjPtr port;
port = GetVar(object, PORTNUMBER);
if (port)
{
int portDev;
int begin, end, firstBegin;
int k;
portDev = GetInt(port);
/*Search for blank area and go to record standby*/
for (k = 0; k < NRETRIES; ++k)
{
SendCmd(portDev, REC_STANDBY);
if (WaitForCompletion(portDev))
{
goto okbud;
}
ReportError("PrepareToRecordLVR5000", "REC_STANDBY did not complete");
}
return ObjFalse;
okbud:
/*Get first blank area*/
SendPort(portDev, CURRENT_BLANK_INQ);
firstBegin = begin = Read5Digits(portDev);
if (begin < 0) return ObjFalse;
end = Read5Digits(portDev);
if (end < 0) return ObjFalse;
/*If not enough, search for more*/
if (end - begin <= nFrames)
{
do
{
if (SendCmd(portDev, EDGE_RIGHT))
{
if (WaitForCompletion(portDev))
{
SendPort(portDev, CURRENT_BLANK_INQ);
begin = Read5Digits(portDev);
if (begin < 0) return ObjFalse;
end = Read5Digits(portDev);
if (end < 0) return ObjFalse;
}
else
{
ReportError("PrepareToRecordLVR5000", "EDGE_RIGHT did not complete");
return ObjFalse;
}
}
else
{
ReportError("PrepareToRecordLVR5000", "EDGE_RIGHT did not complete");
return ObjFalse;
}
} while (begin != firstBegin && end - begin <= nFrames);
if (end - begin <= nFrames)
{
ReportError("PrepareToRecordLVR5000", "There is not enough space on the disc");
return ObjFalse;
}
}
/*Say for the range we need*/
SendNumber(portDev, begin);
SendNumber(portDev, begin + nFrames);
SendCmd(portDev, ENTER);
if (!WaitForCompletion(portDev))
{
return ObjFalse;
}
SendCmd(portDev, FRAME_REC);
return ObjTrue;
}
else
{
return ObjFalse;
}
}
static ObjPtr StopRecordingLVR5000(object)
ObjPtr object;
/*Stops recording*/
{
ObjPtr port;
port = GetVar(object, PORTNUMBER);
if (port)
{
int portDev;
portDev = GetInt(port);
SendCmd(portDev, ALL_CLEAR);
return ObjTrue;
}
else
{
return ObjFalse;
}
}
static ObjPtr DisconnectLVR5000(object)
ObjPtr object;
{
int portDev;
ObjPtr port;
port = GetVar(object, PORTNUMBER);
if (port)
{
portDev = GetInt(port);
close(portDev);
SetVar(object, PORTNUMBER, NULLOBJ);
}
return ObjTrue;
}
static ObjPtr SnapOneFrameLVR5000(object)
ObjPtr object;
{
int portDev;
int test;
ObjPtr port;
port = GetVar(object, PORTNUMBER);
if (port)
{
portDev = GetInt(port);
test = SendCmd(portDev, REC);
if (!WaitForCompletion(portDev))
{
return ObjFalse;
}
return test ? ObjTrue : ObjFalse;
}
else
{
return ObjTrue;
}
}
#endif
#ifdef PROTO
void InitLVR5000(void)
#else
void InitLVR5000()
#endif
/*Create a new LVR-5000 object*/
{
#ifdef TERMIO
ObjPtr recorder;
char *devName;
recorder = NewRecorder(commRecorderClass, "LVR-5000", "Sony");
SetMethod(recorder, CONNECT, ConnectLVR5000);
SetMethod(recorder, DISCONNECT, DisconnectLVR5000);
SetMethod(recorder, PREPARETORECORD, PrepareToRecordLVR5000);
SetMethod(recorder, STOPRECORDING, StopRecordingLVR5000);
SetMethod(recorder, SNAPONEFRAME, SnapOneFrameLVR5000);
devName = getenv("SCIAN_RECORDER_DEV");
if (!devName || !devName[0])
{
devName = LVR5000_DEV;
}
SetVar(recorder, PORTDEV, NewString(devName));
RegisterRecorder(recorder);
#endif
}
#ifdef PROTO
void KillLVR5000(void)
#else
void KillLVR5000()
#endif
{
}